﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using EFExtention.Common.DataModel;
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Mvvm.POCO;

namespace EFExtention.Common.ViewModel {
    partial class SingleObjectViewModel<TEntity, TPrimaryKey, TUnitOfWork> : IBaseViewModel
        where TEntity : class
        where TUnitOfWork : IUnitOfWork {
        public new bool IsNew() { return base.IsNew(); }
        public TPrimaryKey EntityKey { get { return Entity == null ? default(TPrimaryKey) : GetPrimaryKey(Entity); } }
        protected override bool HasValidationErrors() {
            return ValidationErrors;
        }
        public virtual bool ValidationErrors { get; set; }
        protected virtual void OnValidationErrorsChanged() {
            UpdateCommands();
        }
        [Command]
        public bool Cancel() {
            base.Reload();
            return true;
        }
        bool IBaseViewModel.NeedSave { get { return NeedSave(); } }

        [Command]
        public new void Reload() {
            if(Entity != null) {
                Entity = Repository.Reload(Entity);
                OnEntityChanged();
                this.RaisePropertyChanged(x => x.Entity);
            }
        }
        public bool CanReload() {
            return NeedSave();
        }
        protected override void UpdateCommands() {
            base.UpdateCommands();
            this.RaiseCanExecuteChanged(x => x.Reload());
            this.RaiseCanExecuteChanged(x => x.SaveAndClose());
        }
        [Command]
        public void CancelAndClose() {
            if(Cancel())
                Close();
        }
        [Command]
        public void SaveAndClose() {
            if(Save())
                Close();
        }
        public bool CanSaveAndClose() {
            return CanSave();
        }
        public override bool CanSave() {
            return base.CanSave() && NeedSave();
        }
        protected override void OnParameterChanged(object parameter) {
            base.OnParameterChanged(parameter);
            if(object.Equals(parameter, SingleObjectViewModelParameter.CreateNew))
                Entity = CreateEntity();
        }
        protected virtual bool EnableSelectedItemSynchronization {
            get { return false; }
        }
        protected override void OnInitializeInRuntime() {
            base.OnInitializeInRuntime();
            if(EnableSelectedItemSynchronization)
                SubscribeSelectedItemSynchronizationMessage();
        }
        protected void SubscribeSelectedItemSynchronizationMessage() {
            Messenger.Default.Register<SelectedItemSynchronizationMessage<TEntity>>(this, x => OnSelectedItemSynchronizationMessage(x));
        }
        protected virtual void OnSelectedItemSynchronizationMessage(SelectedItemSynchronizationMessage<TEntity> m) {
            if(m.Entity == null) Entity = null;
            else OnParameterChanged(GetPrimaryKey(m.Entity));
        }
        protected virtual bool EnableEntityChangedSynchronization {
            get { return false; }
        }
        protected override void OnEntityMessage(EntityMessage<TEntity> msg) {
            if(EnableEntityChangedSynchronization && msg.MessageType == EntityMessageType.Changed) {
                if(object.Equals(GetPrimaryKey(msg.Entity), GetPrimaryKey(Entity)))
                    Reload();
            }
            base.OnEntityMessage(msg);
        }
        [ServiceProperty(SearchMode = ServiceSearchMode.PreferParents)]
        protected virtual IDocumentManagerService DocumentManagerService { get { return null; } }
    }
    public interface IBaseViewModel {
        bool Save();
        bool NeedSave { get; }
        bool Cancel();
    }
    public enum SingleObjectViewModelParameter {
        CreateNew
    }
}
